import * as Color from '../theme/color'
import { EChartsOption, LinearGradientObject, ToolboxComponentOption, TooltipComponentOption, XAXisComponentOption, YAXisComponentOption } from 'echarts'
import { sortBy } from 'lodash'

export function genLinearGradient(from: string, to: string, type: 'x' | 'y' = 'y'): LinearGradientObject {
  return {
    type: 'linear',
    x: 1,
    y: 0,
    x2: type === 'x' ? 0 : 1,
    y2: type === 'y' ? 1 : 0,
    colorStops: [
      { offset: 0, color: from },
      { offset: 1, color: to }
    ]
  }
}

export function genToolbox(isZoom = false): ToolboxComponentOption {
  const options: ToolboxComponentOption = {
    show: true,
    feature: { saveAsImage: { backgroundColor: Color.char500 } }
  }
  isZoom && (options.feature!.dataZoom = { yAxisIndex: 'none' })
  return options
}

export function genTooltip(): TooltipComponentOption {
  return {
    trigger: 'axis',
    borderWidth: 0,
    backgroundColor: Color.main500,
    textStyle: { color: Color.char500 },  
  }
}

export function genYAxis(): YAXisComponentOption {
  return {
    axisLine: { show: false },
    axisTick: { show: false },
    axisLabel: {
      show: true, color: Color.char500,
    },
    splitLine: {
      show: true,
      lineStyle: { type: 'dashed', color: Color.char700 }
    }
  }
}

export function genXAxis(): XAXisComponentOption {
  return {
    splitLine: { show: false },
    axisLine: {
      show: true,
      lineStyle: { color: Color.char700 }
    },
    axisTick: {
      show: true,
      lineStyle: { color: Color.char700 }
    },
    axisLabel: { show: true, color: Color.char500 }
  }
}

export interface CatalogChartDataItem {
  catalog: string,
  value: number
}
export function composeCatalogCharts(
  datas: CatalogChartDataItem[][],
  names: string[],
  fromColors: string[],
  toColor: string,
  gridX: string,
  gridY: string,
  options?: {
    min?: number,
    max?: number,
    reverse?: boolean,
    sort?: number
  }
): EChartsOption {
  let yAxis: YAXisComponentOption
  let xAxis: XAXisComponentOption
  let encode: { x: string, y: string }
  if (!options?.reverse) {
    yAxis = { min: options?.min, max: options?.max, ...genYAxis() }
    xAxis = { type: 'category', ...genXAxis() }
    encode = { x: 'catalog', y: 'value' }
  } else {
    yAxis = { type: 'category', ...genYAxis() }
    xAxis = { min: options?.min, max: options?.max, ...genXAxis() }
    encode = { x: 'value', y: 'catalog' }
  }

  if (options?.sort) {
    const ratio = options.sort
    datas = datas.map(x => sortBy(x, (o) => ratio * o.value))
  }
  
  return {
    tooltip: genTooltip(),
    toolbox: genToolbox(true),
    yAxis,
    xAxis,
    grid: { top: gridY, bottom: gridY, left: gridX, right: gridX },
    series: datas.map((data, index) => ({
      type: 'bar',
      datasetIndex: index,
      name: names[index],
      encode,
      itemStyle: { color: genLinearGradient(fromColors[index], toColor, options?.reverse ? 'x' : 'y') }
    })),
    dataset: datas.map(data => ({ source: data }))
  }
}

export interface TimeChartDataItem {
  time: string,
  value: number
}
export type TimeChartsType = 'bar' | 'line'
export function composeTimeCharts(
  datas: TimeChartDataItem[][],
  types: TimeChartsType[],
  names: string[],
  fromColors: string[],
  toColor: string,
  gridX: string,
  gridY: string,
  options?: {
    min?: number,
    max?: number,
    noArea?: boolean
  }
): EChartsOption {
  return {
    legend: {
      textStyle:{ color: Color.char500 },
      data: names
    },
    tooltip: genTooltip(),
    toolbox: genToolbox(true),
    yAxis: { min: options?.min, max: options?.max, ...genYAxis() },
    xAxis: { type: 'time', ...genXAxis() },
    grid: { top: gridY, bottom: gridY, left: gridX, right: gridX },
    series: types.map((type, index) => ({
      type,
      datasetIndex: index,
      name: names[index],
      encode: { x: 'time', y: 'value' },
      smooth: true,
      showSymbol: false,
      areaStyle: options?.noArea ? { color: '#00000000' } : { color: genLinearGradient(fromColors[index], toColor) } ,
      lineStyle: { width: 2, color: fromColors[index] },
      itemStyle: { color: fromColors[index], borderWidth: 1 },
    })),
    dataset: datas.map(data => ({ source: data }))
  }
}